package delegate4j;

import com.sun.istack.internal.NotNull;
import com.sun.istack.internal.Nullable;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public abstract class Delegate<S extends IDelegate> implements Serializable {

    protected final List<S> delegates = new ArrayList<S>();

    private Delegate() {
    }

    public Delegate(@NotNull S delegate) {
        delegates.add(delegate);
    }

    public void combine(List<S> delegates) {
        for (S s : delegates) {
            if (!contains(s))
                this.delegates.add(s);
        }
    }

    public void add(S delegate) {
        if (!contains(delegate))
            delegates.add(delegate);
    }

    public void remove(S delegate) {
        if (contains(delegate))
            delegates.remove(delegate);
    }

    public void clear() {
        delegates.clear();
    }

    public List<S> getInvokeDelegates() {
        return new ArrayList<S>(delegates);
    }

    public boolean contains(S delegate) {
        return delegates.contains(delegate);
    }

    //启动新的线程等待所有线程运行结束
    protected <TResult> void waitTasksFinish(
            @NotNull ArrayList<FutureTask<TResult>> tasks,
            @Nullable Object[] args,
            @Nullable AsyncDelegateCallback callback) {
        if (callback != null) {
            //启动一个新的线程去等待所有异步委托的运行结束，运行结束后再调用回调函数
            Thread thread = new Thread(() -> {
                Object result = null;
                for (int i = 0; i < tasks.size(); i++) {
                    try {
                        result = tasks.get(i).get();//等待某个线程运行完毕
                    } catch (InterruptedException | ExecutionException e) {
                        e.printStackTrace();
                    }
                }
                try {
                    callback.invoke(this, args, result);//所有线程已经运行完毕，此时调用回调函数
                } catch (Exception e) {
                    System.err.println("在等待委托运行结束时出现异常！");
                    e.printStackTrace();
                }
            });
            thread.start();
        }
    }

}
